# -*- coding: utf-8 -*-
import os


def build(dir_name, dirs):
    # 编译
    for f in os.listdir(dir_name):
        if f.endswith('.proto'):
            command = 'cd %s \n' % dir_name
            command += 'python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. %s' % f
            os.system(command)

    # 修改_pb2_grpc import错误
    for f in os.listdir(dir_name):
        if f.endswith('_pb2_grpc.py'):
            with open(dir_name + f, '+r', encoding="utf-8") as file:
                lines = []
                new_line = ''
                while True:
                    line = file.readline()
                    if not line:
                        break
                    if 'Missing associated' in line or "context.set_details('Method not implemented!')" in line:
                        continue
                    if 'pb2' in line and not new_line:
                        new_line = 'from %s.%s %s\n' % (dirs[-3], dirs[-2], line)
                        lines.append(new_line)
                        lines.append('from common.api import http_result\n')
                        lines.append('from common.utils.session import Session\n')
                        lines.append('import json\n')
                    elif 'context.set_code(grpc.StatusCode.UNIMPLEMENTED)' in line:
                        func = lines[-1].split('(')[0].split(' ')[-1]
                        lines.append('''        param, session = self.param_and_session(request.content)
        if session == 'error':
            return param
        if not session.get('role', None):
            return self.resp(-1, 'login timeout')
        return self.do_%s(param, session)
    
    def do_%s(self, param, session):\n''' % (func, func))
                    else:
                        lines.append(line)

                    # 修改_pb2_grpc 中定义的Servicer
                    if 'Servicer(object)' in line:
                        name = f[:-12]
                        lines.append('    @staticmethod\n')
                        lines.append('    def resp(code, msg, data=None):\n')
                        lines.append(
                            '        return %s__pb2.resp(content=http_result.result(code, msg, data))\n' % name)
                        lines.append('\n')
                        lines.append('    @staticmethod\n')
                        lines.append('    def need_param(param):\n')
                        lines.append('        return %s__pb2.resp(content=http_result.result(0, \'请设置参数: \' + param))\n'
                                     % name)

                        lines.append('''
    def param_and_session(self, content):
        if not content:
            return self.resp(0, '请设置请求参数'), 'error'
        if content:
            content = json.loads(content)
        if 'session_id' not in content:
            return self.resp(0, 'session id is not found'), 'error'
        session = Session(session_id=content['session_id'])
        return content, session
''')

                with open(dir_name + f, 'w', encoding="utf-8") as new_file:
                    new_file.writelines(lines)

    # 修改server, 添加服务监听
    for f in os.listdir(dir_name):
        if f.endswith('service.py'):
            with open(dir_name + f, '+r', encoding="utf-8") as file:
                lines = []
                updating = False
                add_server_lines = []
                while True:
                    line = file.readline()
                    if not line:
                        break
                    if line == '# auto import with build_proto.py\n':
                        updating = True
                        lines.append(line)
                        handler_dir = dir_name.split('rpc')[0] + 'handler' + os.path.sep
                        for f1 in os.listdir(handler_dir):
                            if f1.endswith('.py'):
                                # 查找Servicer
                                with open(handler_dir + f1, 'r', encoding="utf-8") as handler_file:
                                    while True:
                                        line = handler_file.readline()
                                        if 'Servicer' in line and 'Handler' in line and 'class' in line:
                                            py_name = f1.split('.')[0]
                                            handler_name = line.split('r(')[0]
                                            handler_name = handler_name.split(' ')[1] + 'r'
                                            lines.append(
                                                'from %s.handler.%s import %s\n' % (dirs[-3], py_name, handler_name))

                                            # user_pb2_grpc.add_UserServicer_to_server(UserHandler(), grpc_server)
                                            add_server_lines.append(
                                                '    %s_pb2_grpc.add_%sServicer_to_server(%s(), grpc_server)\n' %
                                                (dirs[-3].split('_')[0], handler_name[:-7], handler_name))

                                        if not line:
                                            break

                        for f2 in os.listdir(dir_name):
                            if '_pb2_grpc.py' in f2:
                                lines.append('from %s.%s import %s\n' % (dirs[-3], dirs[-2], f2.split('.')[0]))
                    elif '# 从这里开始是build_proto.py 自动添加' in line:
                        updating = True
                        lines.append(line)
                        for l in add_server_lines:
                            lines.append(l)

                    elif line == '# end auto\n' or '# 自动添加结束' in line:
                        updating = False
                        lines.append(line)
                    else:
                        if not updating:
                            lines.append(line)

            with open(dir_name + f, 'w', encoding="utf-8") as file:
                file.writelines(lines)


def start_build():
    cur_dir = os.getcwd()
    run(dir_name=cur_dir.split('common')[0])


def run(dir_name):
    for f in os.listdir(dir_name):
        path = dir_name + f
        if os.path.isdir(path):
            run(dir_name=path + os.sep)
        if f == 'rpc':
            path += os.path.sep
            print('building ...  ', path)
            build(dir_name=path, dirs=path.split(os.path.sep))


if __name__ == '__main__':
    start_build()
